#include<iostream>
#include<vector>
#include<fstream>
#include<unordered_map>
#include<string>


//this program is so perfect that I want to add some useless codes
int useless;
void useless_codes();



using namespace std;
#define input_doc "/Users/xubin/Desktop/doc.c"//需要进行词法分析的C文件
#define out_doc "/Users/xubin/Desktop/out_doc.txt"//二元组和其他信息输出文件
#define buffer_length 100//缓冲区长度

int state=0 ;//状态
char buffer[buffer_length];//缓冲区
int front_index=buffer_length;//向前指针
char retract_buffer;//回溯缓冲区
int retract_effect=0;//回溯缓冲区是否有效
int words_number=0;//单词个数
int line_number=0;//行数
int key_number=0;//关键字数
int user_number=0;//用户标识符数
int number_number=0;//数字数
int wrong_number=0;//出现错误的词法
ifstream C_doc;//需要进行词法分析的C文件
ofstream output_doc;//二元组和其他信息输出文件
vector<char> token;//当前处理的字符
vector<string> wrong_infomation;//错误信息
vector<int>wrong_line;//错误行数
vector<string>wrong_token;//错误字符

unordered_map<string,int>key_map={
    {"auto",1},{"break",2},{"case",3},{"char",4},{"const",5},{"continue",6},{"default",7},{"do",8},{"double",9},{"else",10},
    {"enum",11},{"extern",12},{"float",13},{"for",14},{"goto",15},{"if",16},{"int",17},{"long",18},{"register",19},{"return",20},
    {"short",21},{"signed",22},{"sizeof",23},{"static",24},{"struct",25},{"switch",26},{"typedef",27},{"unsigned",28},{"union",29},{"void",30},
    {"volatile",31},{"while",32},{"_Alignas",33},{"_Alignof",34},{"_Atomic",35},{"_Bool",36},{"_Complex",37},{"_Generic",38},{"_Imaginary",39},{"_Noreturn",40},{"_Static_assert",41},{"_Thread_local",42}//注意是1开头的
};
unordered_map<string,int>user_map;//用户自定义变量表
unordered_map<string, int>op_map={
    {"//",1},{"/*",2},{"*/",3},{"/",4},{"/=",5},{"+",6},{"++",7},{"+=",8},{"-",9},{"--",10},{"-=",11},{"*",12},{"*=",13},{"%",14},{"%=",15},{"<",16},{"<<",17},{"<=",18},{"<<=",19},{">",20},{">>",21},{">=",22},{">>=",23},{"=",24},{"==",25},{"!",26},{"!=",27},{"&",28},{"&=",29},{"&&",30},{"|",31},{"||",32},{"|=",33},{"~",34},{"^",35},{"?",36},{"(",37},{")",38},{"{",39},{"}",40},{"[",41},{"]",42},{".",43},{";",44},{":",45},{",",46},{"->",47}
};//符号表

char problem_solve(string wrong_info);//错误处理函数
int fit_buffer();//从文件中将字符读入缓冲区
char get_char();//返回向前指针后第一个字符。处理缓冲区读写。
char get_nbc();//返回向前指针后第一个非零字符。(包括EOF)
//判断传入的字符串是否为关键字，若是，则返回关键字索引，若不是，则返回-1
int is_key(string characters);
//判断传入的字符串是否已出现在用户变量表中。若在，则返回变量表索引，若不是，则在变量表中新建一个条目并返回其索引。
int user_map_process(string characters);
//处理记号，将记号转换为对应类型的函数
string token2string(vector<char>token);//将token转为字符串类型
int token2int(vector<char>token);//将token转为整数类型
double token2double(vector<char>token);//将token转为小数类型
double token2exp(vector<char>token);//将token转为科学计数法类型
int token2binary(vector<char>token);//将token二进制类型转为十进制
int token2hex(vector<char>token);//将token十六进制类型转为十进制
int token2oct(vector<char>token);//将token八进制类型转为十进制
//词法分析主体程序
void lexer_main();



int main(){
    C_doc.open(input_doc);
    output_doc.open(out_doc);
    lexer_main();//进行词法分析程序处理
    output_doc<<"错误数为"<<wrong_number<<endl;
    output_doc<<"错误统计如下："<<endl;
    for(int i=0;i<wrong_infomation.size();i++){
        output_doc<<wrong_infomation[i]<<wrong_token[i]<<"  行数为："<<wrong_line[i]<<endl;
    }
    output_doc<<"行数为"<<line_number<<endl;//包括了注释所在行数
    output_doc<<"总单词个数为"<<words_number<<endl;//没问题，包括了出错的单词，也视为一个单词。
    output_doc<<"数字数为"<<number_number<<endl;
    output_doc<<"用户自定义标识符数为"<<user_number<<endl;
    output_doc<<"用户自定义标识符表序号及字符串如下："<<endl;
    for(unordered_map<string, int>::iterator iter=user_map.begin();iter!=user_map.end();iter++){
        output_doc<<iter->second<<"  "<<iter->first<<endl;
        cout<<iter->second<<"  "<<iter->first<<endl;
    }
    output_doc<<"所包含关键字数为"<<key_number<<endl;
    cout<<"错误数为"<<wrong_number<<endl;
    cout<<"行数为"<<line_number<<endl;//包括了注释所在行数
    cout<<"总单词个数为"<<words_number<<endl;//没问题，包括了出错的单词，也视为一个单词。
    cout<<"数字数为"<<number_number<<endl;
    cout<<"用户自定义标识符数为"<<user_number<<endl;
    cout<<"所包含关键字数为"<<key_number<<endl;
    output_doc.close();
    C_doc.close();
}

//从文件中将字符读入缓冲区
int fit_buffer(){
    if(C_doc.is_open()){
        int i=0;
        char ch;
        for(i=0;!C_doc.eof()&&i<buffer_length;i++){
            C_doc.get(ch);
            if(C_doc.fail())//不这样处理则会在读取到EOF时多读取一个字符。
                break;
            buffer[i]=ch;
        }
        //在缓冲区末尾加入EOF
        if(C_doc.eof()){
            if(i<buffer_length){
                buffer[i]=EOF;
                return 2;//文件结束，eof可以放入缓冲区内
            }
        }
        return 1;//正常返回，文件未到结尾。
    }
    cout<<"文件打开失败";
    return 0;

}
char get_char(){//返回向前指针后第一个字符。处理缓冲区读写。
    if(retract_effect==1){
        retract_effect=0;
        return retract_buffer;//回溯缓冲区有效则直接返回
    }
    if(front_index==buffer_length){//当前缓冲区已到达末尾
        int state=fit_buffer();//填充新缓冲区
        switch (state) {
            case 0:
                return EOF;//文件打开失败则直接返回EOF，阻止后续读入
                break;
            case 1:case 2:
                front_index=0;//不必担心EOF的问题。
                break;
            default:
                return EOF;//直接返回EOF，阻止后续读入
                break;
        }
    }
    return buffer[front_index++];
}

//返回向前指针后第一个非零字符。(包括EOF)
char get_nbc(){
    char c=get_char();
    while(c==' '||c=='\t'||c=='\r'||c=='\n'||c=='\0'){
        if(c=='\n')
            line_number++;
        c=get_char();
    }
    return c;
}

//判断传入的字符串是否为关键字，若是，则返回关键字索引，若不是，则返回-1
int is_key(string characters){
    int result=-1;
    try{
        result=key_map.at(characters);
    }
    catch(out_of_range){
        return -1;
    }
    return result;
}

//判断传入的字符串是否已出现在用户变量表中。若在，则返回变量表索引，若不是，则在变量表中新建一个条目并返回其索引。
int user_map_process(string characters){
    int result=-1;
    try{
        result=user_map.at(characters);
    }
    catch(out_of_range){
        user_map.emplace(characters,user_map.size()+1);
        return user_map.size();
    }
    return result;
}

//处理记号，将记号转换为对应类型的函数
string token2string(vector<char>token){
    string result;
    for(vector<char>::iterator iter=token.begin();iter!=token.end();iter++)
            result+=(*iter);
    return result;
}
int token2int(vector<char>token){
    int result=0;
    for(vector<char>::iterator iter=token.begin(); iter!=token.end();iter++)
            result=result*10+((*iter)-'0');
    return result;
}
double token2double(vector<char>token){
    int result_int=0;
    double result_float=0;
    for(vector<char>::iterator iter=token.begin();(*iter)!='.';iter++)
            result_int= result_int*10+((*iter)-'0');
    for(vector<char>::iterator iter=token.end()-1;(*iter)!='.';iter--){
        result_float= result_float*0.1+((*iter)-'0');
    }
    return result_int+result_float*0.1;
}
double token2exp(vector<char>token){
    int result_int=0;
    double result_float=0;
    int exp=0;
    int this_state=0;
    for(vector<char>::iterator iter=token.begin();iter!=token.end();iter++){
        if((*iter)=='.'){
            this_state=1;
            iter++;
        }
        else if((*iter)=='E'){
            this_state=2;
            iter++;
        }
        if(this_state==0)
            result_int= result_int*10+((*iter)-'0');
        else if(this_state==1)
            result_float= result_float*0.1+((*iter)-'0');
        else if(this_state==2)
            exp=exp*10+((*iter)-'0');
    }
    double result=(result_float*0.1+result_int)*pow(10, exp);
    return result;
}

int token2binary(vector<char>token){
    int result=0;
    for(int i=2;i<token.size();i++)
            result=result*2+(token[i]-'0');
    return result;
}

int token2hex(vector<char>token){
    int result=0;
    for(int i=2;i<token.size();i++){
        if(isnumber(token[i]))
            result=result*16+token[i]-'0';
        else if(islower(token[i]))
            result=result*16+token[i]-'a';
        else if(isupper(token[i]))
            result=result*16+token[i]-'A';
    }
    return result;
}
int token2oct(vector<char>token){
    int result=0;
    for(int i=1;i<token.size();i++)
        result=result*8+token[i]-'0';
    return result;
}

//词法分析主体程序，具体转移状态信息参见实验报告
void lexer_main(){
    state=0;
    char c='\0';
    do{
        switch (state) {
            case 0:
                if(c==EOF)//错误处理后若第一个字符恰好是EOF，则在get_nbc之前即返回。
                    return;
                token.clear();
                c=get_nbc();
                if(c==EOF)//如果已经到达文件末尾，则直接返回。
                    return;
                words_number++;//否则这将是一个字符的起始。字符数+1
                switch (c) {
                    case '_':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z'://变量
                        state=1;
                        break;
                        
                    case'\'':state=2;break;
                    case'\"':state=12;break;
                        
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9'://数字
                        state=13;break;
                    case '0':state=19;break;//其他进制处理
                    case '/':state=30;break;
                    //运算符类
                    case '+':state=41;break;
                    case '-':state=42;break;
                    case '*':state=43;break;
                   // case '/':state=44;//state与注释块合并
                    case '%':state=45;break;
                    case '>':state=47;break;
                    case '<':state=46;break;
                    case '=':state=48;break;
                    case '!':state=49;break;
                    case '&':state=50;break;
                    case '|':state=51;break;
                        //此之后的字符均为单个字符。直接转入state=0?
                    case '~':case '^':case '?':case '(':case ')':case '{':case '}':case '[':case ']':case '.':case ';':case ':':case ',':{
                        token.push_back(c);
                        //将对应的符号存入文件
                        string temp;
                        temp+=c;
                        output_doc<<"(OP,"<<op_map.at(temp)<<')'<<endl;
                        cout<<"(OP,"<<op_map.at(temp)<<')'<<temp<<endl;
                        state=0;
                        break;
                    }
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的符号输入");
                        break;
                }
                break;
        //状态1,标识符
            case 1:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '_':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case '0':
                        state=1;
                        break;
                    case ';':case',':case' ':case'\n':case '\0':case'\t':case'\r':case')':case'+':case'-':case'*':case'/':case'%':case'&':case'|':case'=':case'[':case'{':case'(':case'!':case'.':case':':case'?':case'<':case'>':case']':case'}':case'\'':{
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        string characters=token2string(token);
                        int id_number=is_key(characters);
                        if(id_number==-1){
                            id_number=user_map_process(characters);//进行用户自定义标识符处理
                            //输出用户自定义标识符
                            user_number++;
                            output_doc<<"(Id,"<<id_number<<')'<<endl;
                            cout<<"(Id,"<<id_number<<')'<<characters<<endl;
                        }
                        else{
                            //输出关键字
                            key_number++;
                            output_doc<<"(Key,"<<id_number<<')'<<endl;
                            cout<<"(Key,"<<id_number<<')'<<characters<<endl;
                        }
                        break;
                    }
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的标识符");
                        break;
                    }
                break;
                //数字类型处理
            case 13:
                token.push_back(c);
                c=get_char();
                switch(c){
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case '0'://数字
                        state=13;
                        break;
                    case'.':state=14;break;
                    case'E':state=16;break;
                    case ';':case',':case' ':case'\n':case '\0':case'\t':case'\r':case')':case'+':case'-':case'*':case'/':case'%':case'&':case'|':case'=':case']':case'}':case'\'':case':':case'<':case'>':case'!':case '?':{
                        retract_buffer=c;
                        retract_effect=1;//需要回溯
                        state=0;
                        //输出
                        int number=token2int(token);
                        number_number++;
                        output_doc<<"(Num,"<<number<<')'<<endl;
                        cout<<"(Num,"<<number<<')'<<endl;
                        break;
                    }
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的整数");
                        break;
                }
                break;
            case 14:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case '0'://数字
                        state=15;
                        break;
                    default://错误处理
                        token.push_back(c);
                        c=problem_solve("不合法的小数");
                        break;
                }
                break;
            case 15:
                token.push_back(c);
                c=get_char();
                switch(c){
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case '0'://数字
                        state=15;break;
                    case'E':state=16;break;
                    case ';':case',':case' ':case'\n':case '\0':case'\t':case'\r':case')':case'+':case'-':case'*':case'/':case'%':case'&':case'|':case'=':case'}':case'<':case'>':case'!':case'?':{
                        retract_buffer=c;
                        retract_effect=1;//需要回溯
                        double number=token2double(token);
                        number_number++;
                        output_doc<<"(Num,"<<number<<')'<<endl;
                        cout<<"(Num,"<<number<<')'<<endl;
                        state=0;
                        break;
                    }
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的小数");
                        break;
                }
                break;
            case 16:
                token.push_back(c);
                c=get_char();
                switch(c){
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case '0'://数字
                        state=18;break;
                    case'+':case'-':state=17;break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的指数");
                        break;
                }
                break;
            case 17:
                token.push_back(c);
                c=get_char();
                switch(c){
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case '0'://数字
                        state=18;break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的指数");
                        break;
                }
                break;
            case 18:
                token.push_back(c);
                c=get_char();
                switch(c){
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case '0'://数字
                        state=18;break;
                    default:
                        state=0;
                        retract_buffer=c;
                        retract_effect=1;//需要回溯
                        //返回指数打印。
                        double number=token2exp(token);
                        number_number++;
                        output_doc<<"(Num,"<<number<<')'<<endl;
                        cout<<"(Num,"<<number<<')'<<endl;
                        break;
                }
                break;
                //数字处理结束。
            case 30://3开头为注释处理模块
                token.push_back(c);
                c=get_char();
                switch (c){
                    case '/':
                        state=34;
                        token.push_back(c);
                        //输出注释字符至文件(不包括被注释的字符)
                        output_doc<<"(OP,"<<'1'<<')'<<endl;
                        cout<<"(OP,"<<'1'<<')'<<"//"<<endl;
                        break;
                    case '*':
                        state=31;
                        token.push_back(c);
                        //输出左注释符至文件
                        output_doc<<"(OP,"<<'2'<<')'<<endl;
                        cout<<"(OP,"<<'2'<<')'<<"/*"<<endl;
                        break;
                    case '=':
                        state=0;
                        token.push_back(c);
                        //输出/=符至文件
                        output_doc<<"(OP,"<<'5'<<')'<<endl;
                        cout<<"(OP,"<<'5'<<')'<<"/="<<endl;
                        break;
                    default:
                        retract_buffer=c;
                        retract_effect=1;//需要回溯
                        //输出符号/至文件
                        output_doc<<"(OP,"<<'4'<<')'<<endl;
                        cout<<"(OP,"<<'4'<<')'<<"/"<<endl;
                        state=0;
                        break;
                }
                break;
            case 34:
                c=get_char();
                switch (c) {
                    case '\n':
                        line_number++;
                        state=0;//回到初始状态，准备读入下一个字符
                        break;
                    default://其他输入全部忽略
                        state=34;
                        break;
                }
                break;
            case 31:
                c=get_char();
                switch (c) {
                    case '*':
                        token.push_back(c);
                        state=32;
                        break;
                    case '\n':
                        line_number++;
                        state=31;//行数继续+1.
                    default:
                        state=31;
                        break;
                }
                break;
            case 32:
                c=get_char();
                switch(c){
                    case '/':
                        token.push_back(c);
                        state=0;
                        //输出右注释符至文件
                        output_doc<<"(OP,"<<'3'<<')'<<endl;
                        cout<<"(OP,"<<'3'<<')'<<"*/"<<endl;
                        break;
                    default:
                        token.clear();
                        state=31;
                        break;
                }
                break;
            case 19://0开头，有可能是机制也有可能是单零
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case 'b':case 'B':state=21;break;//二进制
                    case'x':case 'X':state=22;break;//十六进制
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '0':state=23;break;//八进制
                    case'.':state=14;break;
                    case ';':case',':case' ':case'\n':case '\0':case'\t':case'\r':case')':case'+':case'-':case'*':case'/':case'%':case'&':case'|':case'=':case':':case']'://单0
                        retract_buffer=c;
                        retract_effect=1;//需要回溯
                        //返回0打印。
                        state=0;
                        number_number++;
                        output_doc<<"(Num,"<<token2int(token)<<')'<<endl;
                        cout<<"(Num,"<<token2int(token)<<')'<<endl;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的进制数表示，检查是否为x/X-十六进制或b/B-二进制或0--7-八进制");
                        break;
                }
                break;
            //处理其他进制
            case 21:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '0':case'1':state=21;break;
                    case ';':case',':case' ':case'\n':case '\0':case'\t':case'\r':case')':case'+':case'-':case'*':case'/':case'%':case'&':case'|':case'=':
                        retract_buffer=c;
                        retract_effect=1;//需要回溯
                        state=0;
                        //返回二进制数打印。
                        number_number++;
                        output_doc<<"(BIN,"<<token2binary(token)<<')'<<endl;
                        cout<<"(BIN,"<<token2binary(token)<<')'<<endl;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的二进制表示");
                        break;
                }
                break;
            case 22:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '0':case'1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':state=22;break;
                    case ';':case',':case' ':case'\n':case '\0':case'\t':case'\r':case')':case'+':case'-':case'*':case'/':case'%':case'&':case'|':case'=':
                        retract_buffer=c;
                        retract_effect=1;//需要回溯
                        //返回十六进制数打印。
                        state=0;
                        number_number++;
                        output_doc<<"(HEX,"<<token2hex(token)<<')'<<endl;
                        cout<<"(HEX,"<<token2hex(token)<<')'<<endl;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的十六进制表示");
                        break;
                }
                break;
            case 23:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '0':case'1':case '2':case '3':case '4':case '5':case '6':case '7':state=23;break;
                    case ';':case',':case' ':case'\n':case '\0':case'\t':case'\r':case')':case'+':case'-':case'*':case'/':case'%':case'&':case'|':case'=':
                        retract_buffer=c;
                        retract_effect=1;//需要回溯
                        //返回八进制数打印。
                        state=0;
                        number_number++;
                        output_doc<<"(OCT,"<<token2oct(token)<<')'<<endl;
                        cout<<"(OCT,"<<token2oct(token)<<')'<<endl;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的八进制表示");
                        break;
                }
                break;
                
            //处理单双引号，其内包括转义字符、单字符和字符串。
            case 2:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '\\':state=3;break;
                    default:
                        state=4;break;
                }
                break;
            case 3:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case 'a':case 'b':case 'f':case 'n':case 'r':case 't':case 'v':case '\\':case '\'':case '\"':case '?':case '\0':
                        state=5;
                        break;
                    case '0':state=70;break;
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':state=6;break;
                    case'x':state=9;break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的转义符号");
                        break;
                }
                break;
            case 70:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case'\'':
                        token.push_back(c);
                        state=0;
                        //输出\0符号至文件
                        output_doc<<"(char,"<<"\0"<<')'<<endl;
                        cout<<"(char,"<<"\0"<<')'<<endl;
                        break;
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':state=7;break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的转义符号");
                        break;
                }
                break;
            case 4:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '\'':
                        state=0;
                        token.push_back(c);
                        //将单个字符存入文件中。
                        //输出
                        output_doc<<"(char,"<<token2string(token)<<')'<<endl;
                        cout<<"(char,"<<token2string(token)<<')'<<token2string(token)<<endl;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("单引号中有多个字符且非转义符号，请使用双引号");
                        break;
                }
                break;
            case 5:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '\'':
                        state=0;
                        token.push_back(c);
                        //转义字符打印。
                        output_doc<<"(special_char,"<<token2string(token)<<')'<<endl;
                        cout<<"(special_char,"<<token2string(token)<<')'<<endl;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的转义符号");
                        break;
                }
                break;
            case 6:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '0':
                        state=7;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的转义符号");
                        break;
                }
                break;
            case 7:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '0':
                        state=8;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的转义符号");
                        break;
                }
                break;
            case 8:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '\'':
                        state=0;
                        token.push_back(c);
                        //将八进制转义字符存入文件
                        output_doc<<"(special_oct,"<<token2string(token)<<')'<<endl;
                        cout<<"(special_oct,"<<token2string(token)<<')'<<endl;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的转义符号");
                        break;
                }
                break;
            case 9:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '0':case'1':case '2':case '3':case '4':case '5':case '6':case '7':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':state=10;break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的转义符号");
                        break;
                }
                break;
            case 10:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '0':case'1':case '2':case '3':case '4':case '5':case '6':case '7':case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
                        state=11;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的转义符号");
                        break;
                }
                break;
            case 11:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '\'':
                        state=0;
                        token.push_back(c);
                        //将十六进制转义字符存入文件
                        output_doc<<"(special_hex,"<<token2string(token)<<')'<<endl;
                        cout<<"(special_hex,"<<token2string(token)<<')'<<endl;
                        break;
                    default:
                        token.push_back(c);
                        c=problem_solve("不合法的转义符号");
                        break;
                }
                break;
            //处理字符串
            case 12:
                token.push_back(c);
                c=get_char();
                if(c!='\"'){
                    state=12;
                    break;
                }
                else{
                    state=0;
                    token.push_back(c);
                    //将字符串输出文件。
                    output_doc<<"(string,"<<token2string(token)<<')'<<endl;
                    cout<<"(string,"<<token2string(token)<<')'<<token2string(token)<<endl;
                }
                break;
                
                
            //处理符号，从41开始
            case 41://+开头
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '+':
                        token.push_back(c);
                        state=0;
                        //输出++符号至文件
                        output_doc<<"(OP,"<<'7'<<')'<<endl;
                        cout<<"(OP,"<<'7'<<')'<<"++"<<endl;
                        break;
                    case'=':
                        token.push_back(c);
                        state=0;
                        //输出+=符号至文件
                        output_doc<<"(OP,"<<'8'<<')'<<endl;
                        cout<<"(OP,"<<'8'<<')'<<"+="<<endl;
                        break;
                    
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将+输出文件
                        output_doc<<"(OP,"<<'6'<<')'<<endl;
                        cout<<"(OP,"<<'6'<<')'<<"+"<<endl;
                        break;
                }
                break;
            case 42://-开头
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '-':
                        token.push_back(c);
                        state=0;
                        //输出--符号至文件
                        output_doc<<"(OP,"<<"10"<<')'<<endl;
                        cout<<"(OP,"<<"10"<<')'<<"--"<<endl;
                        break;
                    case'=':
                        token.push_back(c);
                        state=0;
                        //输出-=符号至文件
                        output_doc<<"(OP,"<<"11"<<')'<<endl;
                        cout<<"(OP,"<<"11"<<')'<<"-="<<endl;
                        break;
                    case'>':
                        token.push_back(c);
                        state=0;
                        //输出->符号至文件
                        output_doc<<"(OP,"<<"47"<<')'<<endl;
                        cout<<"(OP,"<<"47"<<')'<<"->"<<endl;
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将-输出文件
                        output_doc<<"(OP,"<<'9'<<')'<<endl;
                        cout<<"(OP,"<<'9'<<')'<<"-"<<endl;
                        break;
                }
                break;
            case 43://*开头
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case'=':
                        token.push_back(c);
                        state=0;
                        //输出*=符号至文件
                        output_doc<<"(OP,"<<"13"<<')'<<endl;
                        cout<<"(OP,"<<"13"<<')'<<"*="<<endl;
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将*输出文件
                        output_doc<<"(OP,"<<"12"<<')'<<endl;
                        cout<<"(OP,"<<"12"<<')'<<"*"<<endl;
                        break;
                }
                break;
            case 45://%开头
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case'=':
                        token.push_back(c);
                        state=0;
                        //输出%=符号至文件
                        output_doc<<"(OP,"<<"15"<<')'<<endl;
                        cout<<"(OP,"<<"15"<<')'<<"%="<<endl;
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将%输出文件
                        output_doc<<"(OP,"<<"14"<<')'<<endl;
                        cout<<"(OP,"<<"14"<<')'<<"%"<<endl;
                        break;
                }
                break;
            case 46:///<
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case'=':
                        token.push_back(c);
                        state=0;
                        //输出<=符号至文件
                        output_doc<<"(OP,"<<"18"<<')'<<endl;
                        cout<<"(OP,"<<"18"<<')'<<"<="<<endl;
                        break;
                    case'<':
                        state=52;// <<或<<=
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将<输出文件
                        output_doc<<"(OP,"<<"16"<<')'<<endl;
                        cout<<"(OP,"<<"16"<<')'<<"<"<<endl;
                        break;
                }
                break;
            case 52:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '=':
                        token.push_back(c);
                        state=0;
                        //输出<<=符号至文件
                        output_doc<<"(OP,"<<"19"<<')'<<endl;
                        cout<<"(OP,"<<"19"<<')'<<"<<="<<endl;
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将<<输出文件
                        output_doc<<"(OP,"<<"17"<<')'<<endl;
                        cout<<"(OP,"<<"17"<<')'<<"<<"<<endl;
                        break;
                }
                break;
            case 47:// >
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case'=':
                        token.push_back(c);
                        state=0;
                        //输出>=符号至文件
                        output_doc<<"(OP,"<<"22"<<')'<<endl;
                        cout<<"(OP,"<<"22"<<')'<<">="<<endl;
                        break;
                    case'>':
                        state=53;
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将>输出文件
                        output_doc<<"(OP,"<<"20"<<')'<<endl;
                        cout<<"(OP,"<<"20"<<')'<<">"<<endl;
                        break;
                }
                break;
                
            case 53:
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case '=':
                        token.push_back(c);
                        state=0;
                        //输出>>=符号至文件
                        output_doc<<"(OP,"<<"23"<<')'<<endl;
                        cout<<"(OP,"<<"23"<<')'<<">>="<<endl;
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将>>输出文件
                        output_doc<<"(OP,"<<"21"<<')'<<endl;
                        cout<<"(OP,"<<"21"<<')'<<">>"<<endl;
                        break;
                }
                break;
                
            case 48://=开头
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case'=':
                        token.push_back(c);
                        state=0;
                        //输出==符号至文件
                        output_doc<<"(OP,"<<"25"<<')'<<endl;
                        cout<<"(OP,"<<"25"<<')'<<"=="<<endl;
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将=输出文件
                        output_doc<<"(OP,"<<"24"<<')'<<endl;
                        cout<<"(OP,"<<"24"<<')'<<"="<<endl;
                        break;
                }
                break;
            case 49://!开头
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case'=':
                        token.push_back(c);
                        state=0;
                        //输出!=符号至文件
                        output_doc<<"(OP,"<<"27"<<')'<<endl;
                        cout<<"(OP,"<<"27"<<')'<<"!="<<endl;
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将!输出文件
                        output_doc<<"(OP,"<<"26"<<')'<<endl;
                        cout<<"(OP,"<<"26"<<')'<<"!"<<endl;
                        break;
                }
                break;
            case 50://&开头
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case'=':
                        token.push_back(c);
                        state=0;
                        //输出&=符号至文件
                        output_doc<<"(OP,"<<"29"<<')'<<endl;
                        cout<<"(OP,"<<"29"<<')'<<"&="<<endl;
                        break;
                    case'&':
                        token.push_back(c);
                        state=0;
                        //输出&&符号至文件
                        output_doc<<"(OP,"<<"30"<<')'<<endl;
                        cout<<"(OP,"<<"30"<<')'<<"&&"<<endl;
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将&输出文件
                        output_doc<<"(OP,"<<"28"<<')'<<endl;
                        cout<<"(OP,"<<"28"<<')'<<"&"<<endl;
                        break;
                }
                break;
            case 51://|开头
                token.push_back(c);
                c=get_char();
                switch (c) {
                    case'=':
                        token.push_back(c);
                        state=0;
                        //输出|=符号至文件
                        output_doc<<"(OP,"<<"33"<<')'<<endl;
                        cout<<"(OP,"<<"33"<<')'<<"|="<<endl;
                        break;
                    case'|':
                        token.push_back(c);
                        state=0;
                        //输出||符号至文件
                        output_doc<<"(OP,"<<"32"<<')'<<endl;
                        cout<<"(OP,"<<"32"<<')'<<"||"<<endl;
                        break;
                    default:
                        retract_effect=1;
                        retract_buffer=c;
                        state=0;
                        //启用回溯缓冲区机制，下一次的第一次读将直接从缓冲区读入。
                        //将|输出文件
                        output_doc<<"(OP,"<<"31"<<')'<<endl;
                        cout<<"(OP,"<<"31"<<')'<<"|"<<endl;
                        break;
                }
                break;
            default:
                c=problem_solve("不可名状的错误");//正常情况下不会出现
                break;
        }
        
    }while (c!=EOF);
    
}




//错误处理程序
char problem_solve(string wrong_info){
    output_doc<<"当前处理字符"<<token2string(token)<<"错误";//输出错误信息
    cout<<"当前处理字符"<<token2string(token)<<"错误";//输出错误信息
    wrong_token.push_back(token2string(token));
    token.clear();
    output_doc<<"错误类型:"<<wrong_info<<' '<<"错误所在行数:"<<line_number+1<<endl;
    cout<<"错误类型:"<<wrong_info<<' '<<"错误所在行数:"<<line_number+1<<endl;
    wrong_infomation.push_back(wrong_info);
    wrong_line.push_back(line_number+1);
    char c;
    if(retract_effect==1){//若回溯缓冲区有效，则优先从此缓冲区中读取接下来的字符。
        c=retract_buffer;
        retract_effect=0;
    }
    else
        c=get_char();
    while(c!=' '&&c!='\t'&&c!='\r'&&c!='\n'&&c!='\0'&&c!=';'&&c!=','&&c!=EOF&&c!='=')//忽略接下来的字符，直到遇到同步字符集
        c=get_char();
    if(c==';'||c==','||c=='='){//注意回溯，需要保存此类符号并在后续词法分析中输出
        retract_effect=1;
        retract_buffer=c;
    }
    else if(c=='\n')
        line_number++;//统计行数
    state=0;//回到初始状态
    wrong_number++;
    return c;
}
